package com.mao.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mao.common.BaseContext;
import com.mao.common.CustomException;
import com.mao.dto.DishDto;
import com.mao.dto.SetmealDto;
import com.mao.entity.Category;
import com.mao.entity.Dish;
import com.mao.entity.Setmeal;
import com.mao.entity.SetmealDish;
import com.mao.mapper.SetmealMapper;
import com.mao.service.CategoryService;
import com.mao.service.DishService;
import com.mao.service.SetmealDishService;
import com.mao.service.SetmealService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class SetmealServiceImpl extends ServiceImpl<SetmealMapper, Setmeal> implements SetmealService {
    @Autowired
    private SetmealDishService setmealDishService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private DishService dishService;


    @Override
    @Transactional
    public void saveWithDish(SetmealDto setmealDto) {
        //将基本套餐信息保存
        this.save(setmealDto);
        //将里面的关联菜品dish取出来再存放到套餐与菜品关联的表
        List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();
        //遍历集合并赋予id
        List<SetmealDish> setmealDishList = setmealDishes.stream().map((item) -> {
            item.setSetmealId(setmealDto.getId());
            return item;
        }).collect(Collectors.toList());
        //因为数据是json格式，所以用saveBatch方法
        setmealDishService.saveBatch(setmealDishList);
    }

    @Override
    public void removeWithDish(List<Long> ids) {
        //删除套餐基本信息
        LambdaQueryWrapper<Setmeal> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.in(Setmeal::getId,ids);
        queryWrapper.eq(Setmeal::getStatus,"1");
        int count = this.count(queryWrapper);
        if (count>0){
            throw new CustomException("套餐在售卖中，不能删除");
        }else{
            this.removeByIds(ids);
        }

        //删除套餐与菜品的关联数据
        LambdaQueryWrapper<SetmealDish> queryWrapper1=new LambdaQueryWrapper<>();
        queryWrapper1.in(SetmealDish::getSetmealId,ids);
        setmealDishService.remove(queryWrapper1);

    }

    @Override
    public SetmealDto getWithDish(Long id) {
        //1.查询套餐基本信息
        Setmeal setmeal = this.getById(id);
        //2.创建一个聚合类对象
        SetmealDto setmealDto =new SetmealDto();
        //3.拷贝基本属性值过去
        BeanUtils.copyProperties(setmeal,setmealDto);
        //4.创建条件构造器，查询关联菜品，并将查询结果赋值给聚合类
        LambdaQueryWrapper<SetmealDish> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.in(SetmealDish::getSetmealId,id);
        queryWrapper.orderByDesc(SetmealDish::getUpdateTime);
        List<SetmealDish> setmealDishList = setmealDishService.list(queryWrapper);
        setmealDto.setSetmealDishes(setmealDishList);
        //5.加上分类名字
        Category category = categoryService.getById(setmeal.getCategoryId());
        setmealDto.setCategoryName(category.getName());
        return setmealDto;
    }

    @Override
    public void updateWithDish(SetmealDto setmealDto) {
        //1.更新基本套餐信息
        this.updateById(setmealDto);
        //2.删除与套餐关联的菜品
        LambdaQueryWrapper<SetmealDish> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(SetmealDish::getSetmealId,setmealDto.getId());
        setmealDishService.remove(queryWrapper);
        //再从前端传来的菜品进行添加,但是没有id所以要手动赋值
        List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();
        setmealDishes = setmealDishes.stream().map((item) -> {
            item.setSetmealId(setmealDto.getId());
            return item;
        }).collect(Collectors.toList());
        setmealDishService.saveBatch(setmealDishes);
    }

    @Override
    public void status(Integer status,List<Long> ids) {
        LambdaQueryWrapper<Setmeal> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.in(Setmeal::getId,ids);
        List<Setmeal> setmealList = this.list(queryWrapper);
        setmealList = setmealList.stream().map((item) -> {
            item.setStatus(status);
            return item;
        }).collect(Collectors.toList());
        this.updateBatchById(setmealList);
    }

    @Override
    public List<DishDto> getWithDishDto(Long id) {
        //1.查询出套餐的关联菜品基本信息
        Long userId = BaseContext.getCurrentId();
        LambdaQueryWrapper<SetmealDish> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(SetmealDish::getSetmealId,id);
        List<SetmealDish> setmealDishList = setmealDishService.list(queryWrapper);
        List<DishDto> dishDtoList = setmealDishList.stream().map((item) -> {
            DishDto dishDto = new DishDto();
            //2.拷贝基本信息
            BeanUtils.copyProperties(item, dishDto);
            Dish dish = dishService.getById(item.getDishId());
            //3.拷贝具体菜品信息
            BeanUtils.copyProperties(dish, dishDto);
            return dishDto;
        }).collect(Collectors.toList());

        return dishDtoList;
    }

    @Override
    public List<SetmealDto> get_list(Setmeal setmeal) {
        //创建构造器查询基本套餐信息
        LambdaQueryWrapper<Setmeal> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(setmeal.getStatus()!=null,Setmeal::getStatus,setmeal.getStatus());
        queryWrapper.eq(setmeal.getCategoryId()!=null,Setmeal::getCategoryId,setmeal.getCategoryId());
        queryWrapper.orderByDesc(Setmeal::getUpdateTime);
        List<Setmeal> setmealList = this.list(queryWrapper);
        //根据套餐信息查询关联的菜品信息
        List<SetmealDto> setmealDtoList = setmealList.stream().map((item) -> {
            //先根据categoryId查询分类名称再赋值给聚合setmealDto
            SetmealDto setmealDto = new SetmealDto();
            BeanUtils.copyProperties(item,setmealDto);
            Long categoryId = item.getCategoryId();
            Category category = categoryService.getById(categoryId);
            if (category != null) {
                setmealDto.setCategoryName(category.getName());
            }
            //根据setmealID查询关联的菜品
            LambdaQueryWrapper<SetmealDish> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(SetmealDish::getSetmealId, item.getId());
            lambdaQueryWrapper.orderByDesc(SetmealDish::getUpdateTime);
            List<SetmealDish> setmealDishes = setmealDishService.list(lambdaQueryWrapper);
            setmealDto.setSetmealDishes(setmealDishes);
            return setmealDto;
        }).collect(Collectors.toList());
        return setmealDtoList;
    }

    @Override
    public Page<SetmealDto> page(int page, int pageSize, String name) {
        //1.创建setmeal的分页和setmealDto聚合的分页
        Page<Setmeal> setmealPage=new Page<>(page,pageSize);
        //因为里面有套餐分类的名字属性同时包含setmeal的，而setmeal没这个，所以最后会返回这个的分页数据
        Page<SetmealDto> setmealDtoPage=new Page<>();
        //2.条件构造器
        LambdaQueryWrapper<Setmeal> queryWrapper=new LambdaQueryWrapper<>();
        //3.添加查询条件(主要用于单个查询功能)
        queryWrapper.like(name!=null,Setmeal::getName,name);
        //4.添加排序条件，根据更新时间的降序
        queryWrapper.orderByDesc(Setmeal::getUpdateTime);
        //5.执行查询,查询完后会给setmealPage附上对应的分页数据
        this.page(setmealPage,queryWrapper);
        //6.将对象拷贝到setmealDtoPage,并忽略records属性
        //因为records属性的泛型不一样，一个是setmeal一个是setmealDto所以要将他忽略，自己去手动将records赋值
        BeanUtils.copyProperties(setmealPage,setmealDtoPage,"records");
        List<Setmeal> records = setmealPage.getRecords();
        List<SetmealDto> setmealDtoList = records.stream().map((item) -> {
            //7.先创建一个无数据setmealDto对象
            SetmealDto setmealDto = new SetmealDto();
            //7.1 再将records遍历读取的setmeal对象的属性赋值到setmealDto,所以直接使用拷贝
            BeanUtils.copyProperties(item, setmealDto);
            //7.2 此时还缺一个套餐分类名称所以先根据categoryId查询category（分类）对象
            Category category = categoryService.getById(item.getCategoryId());
            //7.3 根据上面获取到对应的分类对象后直接通过这个分类对象获取其套餐名称,并赋值
            setmealDto.setCategoryName(category.getName() != null ? category.getName() : "未分类套餐");
            //7.4 最后返回其单个套餐对象
            return setmealDto;
            //7.5 以list收集所有返回的对象
        }).collect(Collectors.toList());
        // 7.6 将整个数据类型为SetmealDto的list集合再自己赋值到setmealDtoPage分页构造器
        setmealDtoPage.setRecords(setmealDtoList);
        // 8.最终返回前端
        return setmealDtoPage;
    }


}
